package com.woniuxy.service.impl;

import com.woniuxy.entity.Book;
import com.woniuxy.mapper.BookMapper;
import com.woniuxy.service.BookService;
import org.springframework.data.redis.core.HashOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.List;
import java.util.Random;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.ReentrantLock;

/**
 * @author dingpf
 * @version 1.0
 * @description
 * @create 2025/4/21 16:54
 */
@Service
public class BookSeviceImpl implements BookService {

    @Resource
    private BookMapper bookMapper;

   // @Resource
    //private StringRedisTemplate stringRedisTemplate; // == RedisTemplate<String,String>

    @Resource
    private RedisTemplate redisTemplateInit;  // 默认泛型RedisTemplate<Object,Obeject>

    ReentrantLock lock = new ReentrantLock();

    @Override
    public List<Book> queryAll() {

        return bookMapper.queryAll();
    }

    /**
     * 对该接口数据作缓存
     * redis基本数据类型有五种 String, Hash, set, zset, list
     * String 类型的key默认最小会占512字节，超过就会扩容 512M
     *        有的缓存key,远远达不到512字节，如果缓存了很多这样数据，优点浪费内存，可以用hash数据类型优化
     *
     *  缓存穿透
     *  定义：
     *  解决：1：缓存空对象
     *       缺点：缓存很多垃圾数据
     *       2：利用布隆过滤器（本质就是redis的bitmap（很长的二进制数组）数据类型实现的）
     *
     *
     * @param id
     * @return
     */
    @Override
    public Book queryBookById(Integer id) {
        HashOperations hash = redisTemplateInit.opsForHash();
        Book cacheBook = (Book)hash.get("BOOKSERVICEIMPL:QUERYBYID",id+"");
        if (cacheBook != null){
            return cacheBook;
        }
        boolean b = lock.tryLock();
        try {
            if (b){
                Book book = bookMapper.queryBookById(id);
                //把数据库数据存入redis
                hash.put("BOOKSERVICEIMPL:QUERYBYID",id+"",book == null ? new Book() : book);
                redisTemplateInit.expire("BOOKSERVICEIMPL:QUERYBYID",30, TimeUnit.DAYS);
                return book;
            } else {
                return null; //所有获取到锁线程
            }
        } finally {
            if (lock.isLocked() && lock.isHeldByCurrentThread()){
                lock.unlock(); //释放锁
            }
        }
    }

    /**
     * 延迟双删解决数据一致性问题
     * @param book
     */
    public void updateBook(Book book){
        //1：删除缓存
        //redisTemplateInit.delete("key"); 根据大key删除
        //redisTemplateInit.opsForHash().delete("大key","小key");

        //2: 执行sql语句
        //调mapper

        //3：睡眠一会,睡眠时间根据查询方法运行的时间决定，
        //Thread.sleep(200);

        //4：删除缓存

    }
}
